<!DOCTYPE html>
<html lang="zh-CN" data-theme="light">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <meta name="generator" content="VuePress 2.0.0-beta.38" />
    <meta name="theme" content="VuePress Theme Hope" />
    <meta property="og:url" content="https://javaguide.cn/system-design/framework/spring/spring-common-annotations.html"><meta property="og:site_name" content="JavaGuide"><meta property="og:title" content="Spring/Spring Boot 常用注解总结！"><meta property="og:type" content="article"><meta property="og:image" content="https://javaguide.cn/"><meta property="og:updated_time" content="2022-03-12T05:54:41.000Z"><meta property="og:locale" content="zh-CN"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image:alt" content="Spring/Spring Boot 常用注解总结！"><meta property="article:tag" content="SpringBoot"><meta property="article:tag" content="Spring"><meta property="article:modified_time" content="2022-03-12T05:54:41.000Z"><script>var _hmt = _hmt || [];
      (function() {
        var hm = document.createElement("script");
        hm.src = "https://hm.baidu.com/hm.js?5dd2e8c97962d57b7b8fea1737c01743";
        var s = document.getElementsByTagName("script")[0]; 
        s.parentNode.insertBefore(hm, s);
      })();</script><link rel="stylesheet" href="//at.alicdn.com/t/font_2922463_99aa80ii7cf.css"><title>Spring/Spring Boot 常用注解总结！ | JavaGuide</title><meta name="description" content="Java学习&&面试指南">
    <style>
      :root {
        --bg-color: #fff;
      }

      html[data-theme="dark"] {
        --bg-color: #1d2025;
      }

      html,
      body {
        background-color: var(--bg-color);
      }
    </style>
    <script>
      const userMode = localStorage.getItem("vuepress-theme-hope-scheme");
      const systemDarkMode =
        window.matchMedia &&
        window.matchMedia("(prefers-color-scheme: dark)").matches;

      if (userMode === "dark" || (userMode !== "light" && systemDarkMode)) {
        document.querySelector("html").setAttribute("data-theme", "dark");
      }
    </script>
    <link rel="stylesheet" href="/assets/style.aa943f56.css">
    <link rel="modulepreload" href="/assets/app.93341f6d.js"><link rel="modulepreload" href="/assets/spring-common-annotations.html.d496500e.js"><link rel="modulepreload" href="/assets/spring-common-annotations.html.b0c27cc6.js"><link rel="modulepreload" href="/assets/plugin-vue_export-helper.21dcd24c.js">
  </head>
  <body>
    <div id="app"><!--[--><!--[--><!--[--><span tabindex="-1"></span><a href="#main-content" class="skip-link sr-only">Skip to content</a><!--]--><div class="theme-container has-toc sidebar-open"><!--[--><header class="navbar"><button class="toggle-sidebar-button" title="Toggle Sidebar"><span class="icon"></span></button><a href="/" class="home-link"><img class="logo" src="/logo.png" alt="JavaGuide"><!----><span class="site-name hide-in-pad">JavaGuide</span><!--[--><!----><!--]--></a><nav class="nav-links" style=""><div class="nav-item hide-in-mobile"><a href="/home.html" class="nav-link" arialabel="面试指南"><i class="icon iconfont icon-java"></i>面试指南<!----></a></div><div class="nav-item hide-in-mobile"><a href="/zhuanlan/" class="nav-link" arialabel="优质专栏"><i class="icon iconfont icon-recommend"></i>优质专栏<!----></a></div><div class="nav-item hide-in-mobile"><a href="/open-source-project/" class="nav-link" arialabel="项目精选"><i class="icon iconfont icon-github"></i>项目精选<!----></a></div><div class="nav-item hide-in-mobile"><a href="/books/" class="nav-link" arialabel="书籍精选"><i class="icon iconfont icon-book"></i>书籍精选<!----></a></div><div class="nav-item hide-in-mobile"><a href="https://snailclimb.gitee.io/javaguide/#/" rel="noopener noreferrer" target="_blank" arialabel="旧版链接" class="nav-link"><i class="icon iconfont icon-java"></i>旧版链接<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="nav-item hide-in-mobile"><a href="https://javaguide.cn/feed.json" rel="noopener noreferrer" target="_blank" arialabel="RSS订阅" class="nav-link"><i class="icon iconfont icon-rss"></i>RSS订阅<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="nav-item hide-in-mobile"><a href="/about-the-author/" class="nav-link" arialabel="关于作者"><i class="icon iconfont icon-zuozhe"></i>关于作者<!----></a></div></nav><div class="nav-actions-wrapper"><!--[--><!----><!--]--><div class="nav-item"><!----></div><div class="nav-item"><a class="repo-link" href="https://github.com/Snailclimb/JavaGuide" target="_blank" rel="noopener noreferrer"><svg xmlns="http://www.w3.org/2000/svg" class="icon github-icon" viewbox="0 0 1024 1024" arialabelledby="github" style="width:1.25rem;height:1.25rem;vertical-align:middle;"><title id="github" lang="en">github icon</title><g fill="currentColor"><path d="M511.957 21.333C241.024 21.333 21.333 240.981 21.333 512c0 216.832 140.544 400.725 335.574 465.664 24.49 4.395 32.256-10.07 32.256-23.083 0-11.69.256-44.245 0-85.205-136.448 29.61-164.736-64.64-164.736-64.64-22.315-56.704-54.4-71.765-54.4-71.765-44.587-30.464 3.285-29.824 3.285-29.824 49.195 3.413 75.179 50.517 75.179 50.517 43.776 75.008 114.816 53.333 142.762 40.79 4.523-31.66 17.152-53.377 31.19-65.537-108.971-12.458-223.488-54.485-223.488-242.602 0-53.547 19.114-97.323 50.517-131.67-5.035-12.33-21.93-62.293 4.779-129.834 0 0 41.258-13.184 134.912 50.346a469.803 469.803 0 0 1 122.88-16.554c41.642.213 83.626 5.632 122.88 16.554 93.653-63.488 134.784-50.346 134.784-50.346 26.752 67.541 9.898 117.504 4.864 129.834 31.402 34.347 50.474 78.123 50.474 131.67 0 188.586-114.73 230.016-224.042 242.09 17.578 15.232 33.578 44.672 33.578 90.454v135.85c0 13.142 7.936 27.606 32.854 22.87C862.25 912.597 1002.667 728.747 1002.667 512c0-271.019-219.648-490.667-490.71-490.667z"></path></g></svg></a></div><div class="nav-item hide-in-mobile"><button id="appearance-switch"><svg xmlns="http://www.w3.org/2000/svg" class="icon auto-icon" viewbox="0 0 1024 1024" arialabelledby="auto" style="display:block;"><title id="auto" lang="en">auto icon</title><g fill="currentColor"><path d="M512 992C246.92 992 32 777.08 32 512S246.92 32 512 32s480 214.92 480 480-214.92 480-480 480zm0-840c-198.78 0-360 161.22-360 360 0 198.84 161.22 360 360 360s360-161.16 360-360c0-198.78-161.22-360-360-360zm0 660V212c165.72 0 300 134.34 300 300 0 165.72-134.28 300-300 300z"></path></g></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon dark-icon" viewbox="0 0 1024 1024" arialabelledby="dark" style="display:none;"><title id="dark" lang="en">dark icon</title><g fill="currentColor"><path d="M524.8 938.667h-4.267a439.893 439.893 0 0 1-313.173-134.4 446.293 446.293 0 0 1-11.093-597.334A432.213 432.213 0 0 1 366.933 90.027a42.667 42.667 0 0 1 45.227 9.386 42.667 42.667 0 0 1 10.24 42.667 358.4 358.4 0 0 0 82.773 375.893 361.387 361.387 0 0 0 376.747 82.774 42.667 42.667 0 0 1 54.187 55.04 433.493 433.493 0 0 1-99.84 154.88 438.613 438.613 0 0 1-311.467 128z"></path></g></svg><svg xmlns="http://www.w3.org/2000/svg" class="icon light-icon" viewbox="0 0 1024 1024" arialabelledby="light" style="display:none;"><title id="light" lang="en">light icon</title><g fill="currentColor"><path d="M952 552h-80a40 40 0 0 1 0-80h80a40 40 0 0 1 0 80zM801.88 280.08a41 41 0 0 1-57.96-57.96l57.96-58a41.04 41.04 0 0 1 58 58l-58 57.96zM512 752a240 240 0 1 1 0-480 240 240 0 0 1 0 480zm0-560a40 40 0 0 1-40-40V72a40 40 0 0 1 80 0v80a40 40 0 0 1-40 40zm-289.88 88.08-58-57.96a41.04 41.04 0 0 1 58-58l57.96 58a41 41 0 0 1-57.96 57.96zM192 512a40 40 0 0 1-40 40H72a40 40 0 0 1 0-80h80a40 40 0 0 1 40 40zm30.12 231.92a41 41 0 0 1 57.96 57.96l-57.96 58a41.04 41.04 0 0 1-58-58l58-57.96zM512 832a40 40 0 0 1 40 40v80a40 40 0 0 1-80 0v-80a40 40 0 0 1 40-40zm289.88-88.08 58 57.96a41.04 41.04 0 0 1-58 58l-57.96-58a41 41 0 0 1 57.96-57.96z"></path></g></svg></button></div><form class="search-box" role="search"><input type="search" placeholder="搜索" autocomplete="off" spellcheck="false" value><!----></form><button class="toggle-navbar-button" aria-label="Toggle Navbar" aria-expanded="false" aria-controls="nav-screen"><span class="button-container"><span class="button-top"></span><span class="button-middle"></span><span class="button-bottom"></span></span></button><!--[--><!----><!--]--></div></header><!----><!--]--><!----><div class="toggle-sidebar-wrapper"><span class="arrow left"></span></div><aside class="sidebar"><!--[--><!----><!--]--><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-mianshi"></i><span class="title">面试准备</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-java"></i><span class="title">Java</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-computer"></i><span class="title">计算机基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-database"></i><span class="title">数据库</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-Tools"></i><span class="title">开发工具</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><i class="icon iconfont icon-xitongsheji"></i><span class="title">系统设计</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/system-design/system-design-questions.html" class="nav-link sidebar-link sidebar-page" arialabel="系统设计常见面试总结"><!---->系统设计常见面试总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-basic"></i><span class="title">基础</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><i class="icon iconfont icon-framework"></i><span class="title">常用框架</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable active"><!----><span class="title">Spring</span><span class="arrow down"></span></button><ul class="sidebar-links"><li><!--[--><a href="/system-design/framework/spring/spring-knowledge-and-questions-summary.html" class="nav-link sidebar-link sidebar-page" arialabel="Spring常见问题总结"><!---->Spring常见问题总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html" class="router-link-active router-link-exact-active nav-link active sidebar-link sidebar-page active" arialabel="Spring/Spring Boot 常用注解总结！"><!---->Spring/Spring Boot 常用注解总结！<!----></a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_0-前言" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="0.前言"><!---->0.前言<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_1-springbootapplication" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="1. @SpringBootApplication"><!---->1. @SpringBootApplication<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_2-spring-bean-相关" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="2. Spring Bean 相关"><!---->2. Spring Bean 相关<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_3-处理常见的-http-请求类型" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="3. 处理常见的 HTTP 请求类型"><!---->3. 处理常见的 HTTP 请求类型<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_4-前后端传值" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="4. 前后端传值"><!---->4. 前后端传值<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_5-读取配置信息" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="5. 读取配置信息"><!---->5. 读取配置信息<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_6-参数校验" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="6. 参数校验"><!---->6. 参数校验<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_7-全局处理-controller-层异常" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="7. 全局处理 Controller 层异常"><!---->7. 全局处理 Controller 层异常<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_8-jpa-相关" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="8. JPA 相关"><!---->8. JPA 相关<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_9-事务-transactional" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="9. 事务 @Transactional"><!---->9. 事务 @Transactional<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_10-json-数据处理" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="10. json 数据处理"><!---->10. json 数据处理<!----></a><ul class="sidebar-sub-headers"></ul></li><li class="sidebar-sub-header"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_11-测试相关" class="router-link-active router-link-exact-active nav-link sidebar-link heading" arialabel="11. 测试相关"><!---->11. 测试相关<!----></a><ul class="sidebar-sub-headers"></ul></li></ul><!--]--></li><li><!--[--><a href="/system-design/framework/spring/spring-transaction.html" class="nav-link sidebar-link sidebar-page" arialabel="Spring 事务总结"><!---->Spring 事务总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/system-design/framework/spring/spring-design-patterns-summary.html" class="nav-link sidebar-link sidebar-page" arialabel="Spring 设计模式总结"><!---->Spring 设计模式总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/system-design/framework/spring/spring-boot-auto-assembly-principles.html" class="nav-link sidebar-link sidebar-page" arialabel="Spring Boot 自动装配原理"><!---->Spring Boot 自动装配原理<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><a href="/system-design/framework/mybatis/mybatis-interview.html" class="nav-link sidebar-link sidebar-page" arialabel="MyBatis 常见面试总结"><!---->MyBatis 常见面试总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><a href="/system-design/framework/netty.html" class="nav-link sidebar-link sidebar-page" arialabel="Netty 知识点&amp;面试题总结"><!---->Netty 知识点&amp;面试题总结<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li><li><!--[--><section class="sidebar-group"><p class="sidebar-heading"><!----><span class="title">SpringCloud</span><!----></p><ul class="sidebar-links"><li><!--[--><a href="/system-design/framework/springcloud/springcloud-intro.html" class="nav-link sidebar-link sidebar-page" arialabel="Spring Cloud 入门"><!---->Spring Cloud 入门<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-security-fill"></i><span class="title">安全</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><a href="/system-design/schedule-task.html" class="nav-link sidebar-link sidebar-page" arialabel="Java定时任务大揭秘"><!---->Java定时任务大揭秘<!----></a><ul class="sidebar-sub-headers"></ul><!--]--></li></ul></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-distributed-network"></i><span class="title">分布式</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-et-performance"></i><span class="title">高性能</span><span class="arrow right"></span></button><!----></section><!--]--></li><li><!--[--><section class="sidebar-group"><button class="sidebar-heading clickable"><i class="icon iconfont icon-CalendarAvailability-1"></i><span class="title">高可用</span><span class="arrow right"></span></button><!----></section><!--]--></li></ul><!--[--><!----><!--]--></aside><!--[--><main class="page" id="main-content"><!----><nav class="breadcrumb disable"></nav><div class="page-title"><h1><!---->Spring/Spring Boot 常用注解总结！</h1><div class="article-info"><span class="author-info" arialabel="作者🖊" isoriginal="false" pageview="false" color="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon author-icon" viewbox="0 0 1024 1024" arialabelledby="author"><title id="author" lang="en">author icon</title><g fill="currentColor"><path d="M649.6 633.6c86.4-48 147.2-144 147.2-249.6 0-160-128-288-288-288s-288 128-288 288c0 108.8 57.6 201.6 147.2 249.6-121.6 48-214.4 153.6-240 288-3.2 9.6 0 19.2 6.4 25.6 3.2 9.6 12.8 12.8 22.4 12.8h704c9.6 0 19.2-3.2 25.6-12.8 6.4-6.4 9.6-16 6.4-25.6-25.6-134.4-121.6-240-243.2-288z"></path></g></svg><span><a class="author-item" href="https://javaguide.cn/" target="_blank" rel="noopener noreferrer">Guide</a></span><span property="author" content="Guide"></span></span><span class="category-info" arialabel="分类🌈" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon category-icon" viewbox="0 0 1024 1024" arialabelledby="category"><title id="category" lang="en">category icon</title><g fill="currentColor"><path d="M148.41 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H148.41c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.311-40.31zM147.556 553.478H429.73c22.263 0 40.311 18.048 40.311 40.31v282.176c0 22.263-18.048 40.312-40.31 40.312H147.555c-22.263 0-40.311-18.049-40.311-40.312V593.79c0-22.263 18.048-40.311 40.31-40.311zM593.927 106.992h282.176c22.263 0 40.31 18.048 40.31 40.31V429.48c0 22.263-18.047 40.31-40.31 40.31H593.927c-22.263 0-40.311-18.047-40.311-40.31V147.302c0-22.263 18.048-40.31 40.31-40.31zM730.22 920.502H623.926c-40.925 0-74.22-33.388-74.22-74.425V623.992c0-41.038 33.387-74.424 74.425-74.424h222.085c41.038 0 74.424 33.226 74.424 74.067v114.233c0 10.244-8.304 18.548-18.547 18.548s-18.548-8.304-18.548-18.548V623.635c0-20.388-16.746-36.974-37.33-36.974H624.13c-20.585 0-37.331 16.747-37.331 37.33v222.086c0 20.585 16.654 37.331 37.126 37.331H730.22c10.243 0 18.547 8.304 18.547 18.547 0 10.244-8.304 18.547-18.547 18.547z"></path></g></svg><ul class="categories-wrapper"><li class="category clickable" role="navigation">框架</li><meta property="articleSection" content="框架"></ul></span><span arialabel="标签🏷" isoriginal="false" pageview="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon tag-icon" viewbox="0 0 1024 1024" arialabelledby="tag"><title id="tag" lang="en">tag icon</title><g fill="currentColor"><path d="M939.902 458.563L910.17 144.567c-1.507-16.272-14.465-29.13-30.737-30.737L565.438 84.098h-.402c-3.215 0-5.726 1.005-7.634 2.913l-470.39 470.39a10.004 10.004 0 000 14.164l365.423 365.424c1.909 1.908 4.42 2.913 7.132 2.913s5.223-1.005 7.132-2.913l470.39-470.39c2.01-2.11 3.014-5.023 2.813-8.036zm-240.067-72.121c-35.458 0-64.286-28.828-64.286-64.286s28.828-64.285 64.286-64.285 64.286 28.828 64.286 64.285-28.829 64.286-64.286 64.286z"></path></g></svg><ul class="tags-wrapper"><li class="tag clickable" role="navigation">SpringBoot</li><li class="tag clickable" role="navigation">Spring</li></ul><meta property="keywords" content="SpringBoot,Spring"></span><span class="date-info" arialabel="写作日期📅" isoriginal="false" pageview="false" color="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon calendar-icon" viewbox="0 0 1024 1024" arialabelledby="calendar"><title id="calendar" lang="en">calendar icon</title><g fill="currentColor"><path d="M716.4 110.137c0-18.753-14.72-33.473-33.472-33.473-18.753 0-33.473 14.72-33.473 33.473v33.473h66.993v-33.473zm-334.87 0c0-18.753-14.72-33.473-33.473-33.473s-33.52 14.72-33.52 33.473v33.473h66.993v-33.473zm468.81 33.52H716.4v100.465c0 18.753-14.72 33.473-33.472 33.473a33.145 33.145 0 01-33.473-33.473V143.657H381.53v100.465c0 18.753-14.72 33.473-33.473 33.473a33.145 33.145 0 01-33.473-33.473V143.657H180.6A134.314 134.314 0 0046.66 277.595v535.756A134.314 134.314 0 00180.6 947.289h669.74a134.36 134.36 0 00133.94-133.938V277.595a134.314 134.314 0 00-133.94-133.938zm33.473 267.877H147.126a33.145 33.145 0 01-33.473-33.473c0-18.752 14.72-33.473 33.473-33.473h736.687c18.752 0 33.472 14.72 33.472 33.473a33.145 33.145 0 01-33.472 33.473z"></path></g></svg><span>2021年12月13日</span><meta property="datePublished" content="2021-12-13T09:36:52.000Z"></span><!----><span class="words-info" arialabel="字数🔠" isoriginal="false" pageview="false" color="false"><svg xmlns="http://www.w3.org/2000/svg" class="icon word-icon" viewbox="0 0 1024 1024" arialabelledby="word"><title id="word" lang="en">word icon</title><g fill="currentColor"><path d="M518.217 432.64V73.143A73.143 73.143 0 01603.43 1.097a512 512 0 01419.474 419.474 73.143 73.143 0 01-72.046 85.212H591.36a73.143 73.143 0 01-73.143-73.143z"></path><path d="M493.714 566.857h340.297a73.143 73.143 0 0173.143 85.577A457.143 457.143 0 11371.566 117.76a73.143 73.143 0 0185.577 73.143v339.383a36.571 36.571 0 0036.571 36.571z"></path></g></svg><span>约 5535 字</span><meta property="wordCount" content="5535"></span></div><hr></div><div class="toc-place-holder"><aside id="toc-list"><div class="toc-header">此页内容</div><div class="toc-wrapper"><ul class="toc-list"><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_0-前言" class="router-link-active router-link-exact-active toc-link level3">0.前言</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_1-springbootapplication" class="router-link-active router-link-exact-active toc-link level3">1. @SpringBootApplication</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_2-spring-bean-相关" class="router-link-active router-link-exact-active toc-link level3">2. Spring Bean 相关</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_3-处理常见的-http-请求类型" class="router-link-active router-link-exact-active toc-link level3">3. 处理常见的 HTTP 请求类型</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_4-前后端传值" class="router-link-active router-link-exact-active toc-link level3">4. 前后端传值</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_5-读取配置信息" class="router-link-active router-link-exact-active toc-link level3">5. 读取配置信息</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_6-参数校验" class="router-link-active router-link-exact-active toc-link level3">6. 参数校验</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_7-全局处理-controller-层异常" class="router-link-active router-link-exact-active toc-link level3">7. 全局处理 Controller 层异常</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_8-jpa-相关" class="router-link-active router-link-exact-active toc-link level3">8. JPA 相关</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_9-事务-transactional" class="router-link-active router-link-exact-active toc-link level3">9. 事务 @Transactional</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_10-json-数据处理" class="router-link-active router-link-exact-active toc-link level3">10. json 数据处理</a></li><!----><!--]--><!--[--><li class="toc-item"><a aria-current="page" href="/system-design/framework/spring/spring-common-annotations.html#_11-测试相关" class="router-link-active router-link-exact-active toc-link level3">11. 测试相关</a></li><!----><!--]--></ul></div></aside></div><!----><div class="theme-hope-content"><!--[--><h3 id="_0-前言" tabindex="-1"><a class="header-anchor" href="#_0-前言" aria-hidden="true">#</a> 0.前言</h3><p>可以毫不夸张地说，这篇文章介绍的 Spring/SpringBoot 常用注解基本已经涵盖你工作中遇到的大部分常用的场景。对于每一个注解我都说了具体用法，掌握搞懂，使用 SpringBoot 来开发项目基本没啥大问题了！</p><p><strong>为什么要写这篇文章？</strong></p><p>最近看到网上有一篇关于 SpringBoot 常用注解的文章被转载的比较多，我看了文章内容之后属实觉得质量有点低，并且有点会误导没有太多实际使用经验的人（这些人又占据了大多数）。所以，自己索性花了大概 两天时间简单总结一下了。</p><p><strong>因为我个人的能力和精力有限，如果有任何不对或者需要完善的地方，请帮忙指出！Guide 哥感激不尽！</strong></p><h3 id="_1-springbootapplication" tabindex="-1"><a class="header-anchor" href="#_1-springbootapplication" aria-hidden="true">#</a> 1. <code>@SpringBootApplication</code></h3><p>这里先单独拎出<code>@SpringBootApplication</code> 注解说一下，虽然我们一般不会主动去使用它。</p><p><em>Guide 哥：这个注解是 Spring Boot 项目的基石，创建 SpringBoot 项目之后会默认在主类加上。</em></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootApplication</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SpringSecurityJwtGuideApplication</span> <span class="token punctuation">{</span>
      <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name"><span class="token namespace">java<span class="token punctuation">.</span>lang<span class="token punctuation">.</span></span>String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token class-name">SpringApplication</span><span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token class-name">SpringSecurityJwtGuideApplication</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>我们可以把 <code>@SpringBootApplication</code>看作是 <code>@Configuration</code>、<code>@EnableAutoConfiguration</code>、<code>@ComponentScan</code> 注解的集合。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">package</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot<span class="token punctuation">.</span>autoconfigure</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Target</span><span class="token punctuation">(</span><span class="token class-name">ElementType</span><span class="token punctuation">.</span>TYPE<span class="token punctuation">)</span>
<span class="token annotation punctuation">@Retention</span><span class="token punctuation">(</span><span class="token class-name">RetentionPolicy</span><span class="token punctuation">.</span>RUNTIME<span class="token punctuation">)</span>
<span class="token annotation punctuation">@Documented</span>
<span class="token annotation punctuation">@Inherited</span>
<span class="token annotation punctuation">@SpringBootConfiguration</span>
<span class="token annotation punctuation">@EnableAutoConfiguration</span>
<span class="token annotation punctuation">@ComponentScan</span><span class="token punctuation">(</span>excludeFilters <span class="token operator">=</span> <span class="token punctuation">{</span>
		<span class="token annotation punctuation">@Filter</span><span class="token punctuation">(</span>type <span class="token operator">=</span> <span class="token class-name">FilterType</span><span class="token punctuation">.</span>CUSTOM<span class="token punctuation">,</span> classes <span class="token operator">=</span> <span class="token class-name">TypeExcludeFilter</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token annotation punctuation">@Filter</span><span class="token punctuation">(</span>type <span class="token operator">=</span> <span class="token class-name">FilterType</span><span class="token punctuation">.</span>CUSTOM<span class="token punctuation">,</span> classes <span class="token operator">=</span> <span class="token class-name">AutoConfigurationExcludeFilter</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@interface</span> <span class="token class-name">SpringBootApplication</span> <span class="token punctuation">{</span>
   <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>

<span class="token keyword">package</span> <span class="token namespace">org<span class="token punctuation">.</span>springframework<span class="token punctuation">.</span>boot</span><span class="token punctuation">;</span>
<span class="token annotation punctuation">@Target</span><span class="token punctuation">(</span><span class="token class-name">ElementType</span><span class="token punctuation">.</span>TYPE<span class="token punctuation">)</span>
<span class="token annotation punctuation">@Retention</span><span class="token punctuation">(</span><span class="token class-name">RetentionPolicy</span><span class="token punctuation">.</span>RUNTIME<span class="token punctuation">)</span>
<span class="token annotation punctuation">@Documented</span>
<span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token annotation punctuation">@interface</span> <span class="token class-name">SpringBootConfiguration</span> <span class="token punctuation">{</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br></div></div><p>根据 SpringBoot 官网，这三个注解的作用分别是：</p><ul><li><code>@EnableAutoConfiguration</code>：启用 SpringBoot 的自动配置机制</li><li><code>@ComponentScan</code>： 扫描被<code>@Component</code> (<code>@Service</code>,<code>@Controller</code>)注解的 bean，注解默认会扫描该类所在的包下所有的类。</li><li><code>@Configuration</code>：允许在 Spring 上下文中注册额外的 bean 或导入其他配置类</li></ul><h3 id="_2-spring-bean-相关" tabindex="-1"><a class="header-anchor" href="#_2-spring-bean-相关" aria-hidden="true">#</a> 2. Spring Bean 相关</h3><h4 id="_2-1-autowired" tabindex="-1"><a class="header-anchor" href="#_2-1-autowired" aria-hidden="true">#</a> 2.1. <code>@Autowired</code></h4><p>自动导入对象到类中，被注入进的类同样要被 Spring 容器管理比如：Service 类注入到 Controller 类中。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Service</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserService</span> <span class="token punctuation">{</span>
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>

<span class="token annotation punctuation">@RestController</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/users&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserController</span> <span class="token punctuation">{</span>
   <span class="token annotation punctuation">@Autowired</span>
   <span class="token keyword">private</span> <span class="token class-name">UserService</span> userService<span class="token punctuation">;</span>
   <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h4 id="_2-2-component-repository-service-controller" tabindex="-1"><a class="header-anchor" href="#_2-2-component-repository-service-controller" aria-hidden="true">#</a> 2.2. <code>@Component</code>,<code>@Repository</code>,<code>@Service</code>, <code>@Controller</code></h4><p>我们一般使用 <code>@Autowired</code> 注解让 Spring 容器帮我们自动装配 bean。要想把类标识成可用于 <code>@Autowired</code> 注解自动装配的 bean 的类,可以采用以下注解实现：</p><ul><li><code>@Component</code> ：通用的注解，可标注任意类为 <code>Spring</code> 组件。如果一个 Bean 不知道属于哪个层，可以使用<code>@Component</code> 注解标注。</li><li><code>@Repository</code> : 对应持久层即 Dao 层，主要用于数据库相关操作。</li><li><code>@Service</code> : 对应服务层，主要涉及一些复杂的逻辑，需要用到 Dao 层。</li><li><code>@Controller</code> : 对应 Spring MVC 控制层，主要用于接受用户请求并调用 Service 层返回数据给前端页面。</li></ul><h4 id="_2-3-restcontroller" tabindex="-1"><a class="header-anchor" href="#_2-3-restcontroller" aria-hidden="true">#</a> 2.3. <code>@RestController</code></h4><p><code>@RestController</code>注解是<code>@Controller</code>和<code>@ResponseBody</code>的合集,表示这是个控制器 bean,并且是将函数的返回值直接填入 HTTP 响应体中,是 REST 风格的控制器。</p><p><em>Guide 哥：现在都是前后端分离，说实话我已经很久没有用过<code>@Controller</code>。如果你的项目太老了的话，就当我没说。</em></p><p>单独使用 <code>@Controller</code> 不加 <code>@ResponseBody</code>的话一般是用在要返回一个视图的情况，这种情况属于比较传统的 Spring MVC 的应用，对应于前后端不分离的情况。<code>@Controller</code> +<code>@ResponseBody</code> 返回 JSON 或 XML 形式数据</p><p>关于<code>@RestController</code> 和 <code>@Controller</code>的对比，请看这篇文章：<a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485544&amp;idx=1&amp;sn=3cc95b88979e28fe3bfe539eb421c6d8&amp;chksm=cea247a3f9d5ceb5e324ff4b8697adc3e828ecf71a3468445e70221cce768d1e722085359907&amp;token=1725092312&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">@RestController vs @Controller<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>。</p><h4 id="_2-4-scope" tabindex="-1"><a class="header-anchor" href="#_2-4-scope" aria-hidden="true">#</a> 2.4. <code>@Scope</code></h4><p>声明 Spring Bean 的作用域，使用方法:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Bean</span>
<span class="token annotation punctuation">@Scope</span><span class="token punctuation">(</span><span class="token string">&quot;singleton&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">Person</span> <span class="token function">personSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p><strong>四种常见的 Spring Bean 的作用域：</strong></p><ul><li>singleton : 唯一 bean 实例，Spring 中的 bean 默认都是单例的。</li><li>prototype : 每次请求都会创建一个新的 bean 实例。</li><li>request : 每一次 HTTP 请求都会产生一个新的 bean，该 bean 仅在当前 HTTP request 内有效。</li><li>session : 每一个 HTTP Session 会产生一个新的 bean，该 bean 仅在当前 HTTP session 内有效。</li></ul><h4 id="_2-5-configuration" tabindex="-1"><a class="header-anchor" href="#_2-5-configuration" aria-hidden="true">#</a> 2.5. <code>@Configuration</code></h4><p>一般用来声明配置类，可以使用 <code>@Component</code>注解替代，不过使用<code>@Configuration</code>注解声明配置类更加语义化。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Configuration</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AppConfig</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Bean</span>
    <span class="token keyword">public</span> <span class="token class-name">TransferService</span> <span class="token function">transferService</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">TransferServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="_3-处理常见的-http-请求类型" tabindex="-1"><a class="header-anchor" href="#_3-处理常见的-http-请求类型" aria-hidden="true">#</a> 3. 处理常见的 HTTP 请求类型</h3><p><strong>5 种常见的请求类型:</strong></p><ul><li><strong>GET</strong> ：请求从服务器获取特定资源。举个例子：<code>GET /users</code>（获取所有学生）</li><li><strong>POST</strong> ：在服务器上创建一个新的资源。举个例子：<code>POST /users</code>（创建学生）</li><li><strong>PUT</strong> ：更新服务器上的资源（客户端提供更新后的整个资源）。举个例子：<code>PUT /users/12</code>（更新编号为 12 的学生）</li><li><strong>DELETE</strong> ：从服务器删除特定的资源。举个例子：<code>DELETE /users/12</code>（删除编号为 12 的学生）</li><li><strong>PATCH</strong> ：更新服务器上的资源（客户端提供更改的属性，可以看做作是部分更新），使用的比较少，这里就不举例子了。</li></ul><h4 id="_3-1-get-请求" tabindex="-1"><a class="header-anchor" href="#_3-1-get-请求" aria-hidden="true">#</a> 3.1. GET 请求</h4><p><code>@GetMapping(&quot;users&quot;)</code> 等价于<code>@RequestMapping(value=&quot;/users&quot;,method=RequestMethod.GET)</code></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/users&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">List</span><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">&gt;</span><span class="token punctuation">&gt;</span></span> <span class="token function">getAllUsers</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> userRepository<span class="token punctuation">.</span><span class="token function">findAll</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="_3-2-post-请求" tabindex="-1"><a class="header-anchor" href="#_3-2-post-请求" aria-hidden="true">#</a> 3.2. POST 请求</h4><p><code>@PostMapping(&quot;users&quot;)</code> 等价于<code>@RequestMapping(value=&quot;/users&quot;,method=RequestMethod.POST)</code></p><p>关于<code>@RequestBody</code>注解的使用，在下面的“前后端传值”这块会讲到。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/users&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">&gt;</span></span> <span class="token function">createUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Valid</span> <span class="token annotation punctuation">@RequestBody</span> <span class="token class-name">UserCreateRequest</span> userCreateRequest<span class="token punctuation">)</span> <span class="token punctuation">{</span>
 <span class="token keyword">return</span> userRespository<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>userCreateRequest<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="_3-3-put-请求" tabindex="-1"><a class="header-anchor" href="#_3-3-put-请求" aria-hidden="true">#</a> 3.3. PUT 请求</h4><p><code>@PutMapping(&quot;/users/{userId}&quot;)</code> 等价于<code>@RequestMapping(value=&quot;/users/{userId}&quot;,method=RequestMethod.PUT)</code></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@PutMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/users/{userId}&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">&gt;</span></span> <span class="token function">updateUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;userId&quot;</span><span class="token punctuation">)</span> <span class="token class-name">Long</span> userId<span class="token punctuation">,</span>
  <span class="token annotation punctuation">@Valid</span> <span class="token annotation punctuation">@RequestBody</span> <span class="token class-name">UserUpdateRequest</span> userUpdateRequest<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h4 id="_3-4-delete-请求" tabindex="-1"><a class="header-anchor" href="#_3-4-delete-请求" aria-hidden="true">#</a> 3.4. <strong>DELETE 请求</strong></h4><p><code>@DeleteMapping(&quot;/users/{userId}&quot;)</code>等价于<code>@RequestMapping(value=&quot;/users/{userId}&quot;,method=RequestMethod.DELETE)</code></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@DeleteMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/users/{userId}&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span> <span class="token function">deleteUser</span><span class="token punctuation">(</span><span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;userId&quot;</span><span class="token punctuation">)</span> <span class="token class-name">Long</span> userId<span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><h4 id="_3-5-patch-请求" tabindex="-1"><a class="header-anchor" href="#_3-5-patch-请求" aria-hidden="true">#</a> 3.5. <strong>PATCH 请求</strong></h4><p>一般实际项目中，我们都是 PUT 不够用了之后才用 PATCH 请求去更新数据。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code>  <span class="token annotation punctuation">@PatchMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/profile&quot;</span><span class="token punctuation">)</span>
  <span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span> <span class="token function">updateStudent</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> <span class="token class-name">StudentUpdateRequest</span> studentUpdateRequest<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        studentRepository<span class="token punctuation">.</span><span class="token function">updateDetail</span><span class="token punctuation">(</span>studentUpdateRequest<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token class-name">ResponseEntity</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_4-前后端传值" tabindex="-1"><a class="header-anchor" href="#_4-前后端传值" aria-hidden="true">#</a> 4. 前后端传值</h3><p><strong>掌握前后端传值的正确姿势，是你开始 CRUD 的第一步！</strong></p><h4 id="_4-1-pathvariable-和-requestparam" tabindex="-1"><a class="header-anchor" href="#_4-1-pathvariable-和-requestparam" aria-hidden="true">#</a> 4.1. <code>@PathVariable</code> 和 <code>@RequestParam</code></h4><p><code>@PathVariable</code>用于获取路径参数，<code>@RequestParam</code>用于获取查询参数。</p><p>举个简单的例子：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/klasses/{klassId}/teachers&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Teacher</span><span class="token punctuation">&gt;</span></span> <span class="token function">getKlassRelatedTeachers</span><span class="token punctuation">(</span>
         <span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;klassId&quot;</span><span class="token punctuation">)</span> <span class="token class-name">Long</span> klassId<span class="token punctuation">,</span>
         <span class="token annotation punctuation">@RequestParam</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token string">&quot;type&quot;</span><span class="token punctuation">,</span> required <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token class-name">String</span> type <span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>如果我们请求的 url 是：<code>/klasses/123456/teachers?type=web</code></p><p>那么我们服务获取到的数据就是：<code>klassId=123456,type=web</code>。</p><h4 id="_4-2-requestbody" tabindex="-1"><a class="header-anchor" href="#_4-2-requestbody" aria-hidden="true">#</a> 4.2. <code>@RequestBody</code></h4><p>用于读取 Request 请求（可能是 POST,PUT,DELETE,GET 请求）的 body 部分并且<strong>Content-Type 为 application/json</strong> 格式的数据，接收到数据之后会自动将数据绑定到 Java 对象上去。系统会使用<code>HttpMessageConverter</code>或者自定义的<code>HttpMessageConverter</code>将请求的 body 中的 json 字符串转换为 java 对象。</p><p>我用一个简单的例子来给演示一下基本使用！</p><p>我们有一个注册的接口：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/sign-up&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span> <span class="token function">signUp</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> <span class="token annotation punctuation">@Valid</span> <span class="token class-name">UserRegisterRequest</span> userRegisterRequest<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  userService<span class="token punctuation">.</span><span class="token function">save</span><span class="token punctuation">(</span>userRegisterRequest<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token class-name">ResponseEntity</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p><code>UserRegisterRequest</code>对象：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Data</span>
<span class="token annotation punctuation">@AllArgsConstructor</span>
<span class="token annotation punctuation">@NoArgsConstructor</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">UserRegisterRequest</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@NotBlank</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> userName<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@NotBlank</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> password<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@NotBlank</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> fullName<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><p>我们发送 post 请求到这个接口，并且 body 携带 JSON 数据：</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code><span class="token punctuation">{</span><span class="token property">&quot;userName&quot;</span><span class="token operator">:</span><span class="token string">&quot;coder&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;fullName&quot;</span><span class="token operator">:</span><span class="token string">&quot;shuangkou&quot;</span><span class="token punctuation">,</span><span class="token property">&quot;password&quot;</span><span class="token operator">:</span><span class="token string">&quot;123456&quot;</span><span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>这样我们的后端就可以直接把 json 格式的数据映射到我们的 <code>UserRegisterRequest</code> 类上。</p><p><img src="/assets/@RequestBody.84a28a13.png" alt="" loading="lazy"></p><p>👉 需要注意的是：<strong>一个请求方法只可以有一个<code>@RequestBody</code>，但是可以有多个<code>@RequestParam</code>和<code>@PathVariable</code></strong>。 如果你的方法必须要用两个 <code>@RequestBody</code>来接受数据的话，大概率是你的数据库设计或者系统设计出问题了！</p><h3 id="_5-读取配置信息" tabindex="-1"><a class="header-anchor" href="#_5-读取配置信息" aria-hidden="true">#</a> 5. 读取配置信息</h3><p><strong>很多时候我们需要将一些常用的配置信息比如阿里云 oss、发送短信、微信认证的相关配置信息等等放到配置文件中。</strong></p><p><strong>下面我们来看一下 Spring 为我们提供了哪些方式帮助我们从配置文件中读取这些配置信息。</strong></p><p>我们的数据源<code>application.yml</code>内容如下：</p><div class="language-yaml ext-yml line-numbers-mode"><pre class="language-yaml"><code><span class="token key atrule">wuhan2020</span><span class="token punctuation">:</span> 2020年初武汉爆发了新型冠状病毒，疫情严重，但是，我相信一切都会过去！武汉加油！中国加油！

<span class="token key atrule">my-profile</span><span class="token punctuation">:</span>
  <span class="token key atrule">name</span><span class="token punctuation">:</span> Guide哥
  <span class="token key atrule">email</span><span class="token punctuation">:</span> koushuangbwcx@163.com

<span class="token key atrule">library</span><span class="token punctuation">:</span>
  <span class="token key atrule">location</span><span class="token punctuation">:</span> 湖北武汉加油中国加油
  <span class="token key atrule">books</span><span class="token punctuation">:</span>
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> 天才基本法
      <span class="token key atrule">description</span><span class="token punctuation">:</span> 二十二岁的林朝夕在父亲确诊阿尔茨海默病这天，得知自己暗恋多年的校园男神裴之即将出国深造的消息——对方考取的学校，恰是父亲当年为她放弃的那所。
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> 时间的秩序
      <span class="token key atrule">description</span><span class="token punctuation">:</span> 为什么我们记得过去，而非未来？时间“流逝”意味着什么？是我们存在于时间之内，还是时间存在于我们之中？卡洛·罗韦利用诗意的文字，邀请我们思考这一亘古难题——时间的本质。
    <span class="token punctuation">-</span> <span class="token key atrule">name</span><span class="token punctuation">:</span> 了不起的我
      <span class="token key atrule">description</span><span class="token punctuation">:</span> 如何养成一个新习惯？如何让心智变得更成熟？如何拥有高质量的关系？ 如何走出人生的艰难时刻？
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><h4 id="_5-1-value-常用" tabindex="-1"><a class="header-anchor" href="#_5-1-value-常用" aria-hidden="true">#</a> 5.1. <code>@Value</code>(常用)</h4><p>使用 <code>@Value(&quot;${property}&quot;)</code> 读取比较简单的配置信息：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">&quot;${wuhan2020}&quot;</span><span class="token punctuation">)</span>
<span class="token class-name">String</span> wuhan2020<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h4 id="_5-2-configurationproperties-常用" tabindex="-1"><a class="header-anchor" href="#_5-2-configurationproperties-常用" aria-hidden="true">#</a> 5.2. <code>@ConfigurationProperties</code>(常用)</h4><p>通过<code>@ConfigurationProperties</code>读取配置信息并与 bean 绑定。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Component</span>
<span class="token annotation punctuation">@ConfigurationProperties</span><span class="token punctuation">(</span>prefix <span class="token operator">=</span> <span class="token string">&quot;library&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">class</span> <span class="token class-name">LibraryProperties</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@NotEmpty</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> location<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Book</span><span class="token punctuation">&gt;</span></span> books<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Setter</span>
    <span class="token annotation punctuation">@Getter</span>
    <span class="token annotation punctuation">@ToString</span>
    <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Book</span> <span class="token punctuation">{</span>
        <span class="token class-name">String</span> name<span class="token punctuation">;</span>
        <span class="token class-name">String</span> description<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  省略getter<span class="token operator">/</span>setter
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>你可以像使用普通的 Spring bean 一样，将其注入到类中使用。</p><h4 id="_5-3-propertysource-不常用" tabindex="-1"><a class="header-anchor" href="#_5-3-propertysource-不常用" aria-hidden="true">#</a> 5.3. <code>@PropertySource</code>（不常用）</h4><p><code>@PropertySource</code>读取指定 properties 文件</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Component</span>
<span class="token annotation punctuation">@PropertySource</span><span class="token punctuation">(</span><span class="token string">&quot;classpath:website.properties&quot;</span><span class="token punctuation">)</span>

<span class="token keyword">class</span> <span class="token class-name">WebSite</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">&quot;${url}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> url<span class="token punctuation">;</span>

  省略getter<span class="token operator">/</span>setter
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>更多内容请查看我的这篇文章：<a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247486181&amp;idx=2&amp;sn=10db0ae64ef501f96a5b0dbc4bd78786&amp;chksm=cea2452ef9d5cc384678e456427328600971180a77e40c13936b19369672ca3e342c26e92b50&amp;token=816772476&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">《10 分钟搞定 SpringBoot 如何优雅读取配置文件？》<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> 。</p><h3 id="_6-参数校验" tabindex="-1"><a class="header-anchor" href="#_6-参数校验" aria-hidden="true">#</a> 6. 参数校验</h3><p><strong>数据的校验的重要性就不用说了，即使在前端对数据进行校验的情况下，我们还是要对传入后端的数据再进行一遍校验，避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。</strong></p><p><strong>JSR(Java Specification Requests）</strong> 是一套 JavaBean 参数校验的标准，它定义了很多常用的校验注解，我们可以直接将这些注解加在我们 JavaBean 的属性上面，这样就可以在需要校验的时候进行校验了，非常方便！</p><p>校验的时候我们实际用的是 <strong>Hibernate Validator</strong> 框架。Hibernate Validator 是 Hibernate 团队最初的数据校验框架，Hibernate Validator 4.x 是 Bean Validation 1.0（JSR 303）的参考实现，Hibernate Validator 5.x 是 Bean Validation 1.1（JSR 349）的参考实现，目前最新版的 Hibernate Validator 6.x 是 Bean Validation 2.0（JSR 380）的参考实现。</p><p>SpringBoot 项目的 spring-boot-starter-web 依赖中已经有 hibernate-validator 包，不需要引用相关依赖。如下图所示（通过 idea 插件—Maven Helper 生成）：</p><p><strong>注</strong>：更新版本的 spring-boot-starter-web 依赖中不再有 hibernate-validator 包（如2.3.11.RELEASE），需要自己引入 <code>spring-boot-starter-validation</code> 依赖。</p><p><img src="https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/2021/03/c7bacd12-1c1a-4e41-aaaf-4cad840fc073.png" alt="" loading="lazy"></p><p>非 SpringBoot 项目需要自行引入相关依赖包，这里不多做讲解，具体可以查看我的这篇文章：《<a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485783&amp;idx=1&amp;sn=a407f3b75efa17c643407daa7fb2acd6&amp;chksm=cea2469cf9d5cf8afbcd0a8a1c9cc4294d6805b8e01bee6f76bb2884c5bc15478e91459def49&amp;token=292197051&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">如何在 Spring/Spring Boot 中做参数校验？你需要了解的都在这里！<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>》。</p><p>👉 需要注意的是： <strong>所有的注解，推荐使用 JSR 注解，即<code>javax.validation.constraints</code>，而不是<code>org.hibernate.validator.constraints</code></strong></p><h4 id="_6-1-一些常用的字段验证的注解" tabindex="-1"><a class="header-anchor" href="#_6-1-一些常用的字段验证的注解" aria-hidden="true">#</a> 6.1. 一些常用的字段验证的注解</h4><ul><li><code>@NotEmpty</code> 被注释的字符串的不能为 null 也不能为空</li><li><code>@NotBlank</code> 被注释的字符串非 null，并且必须包含一个非空白字符</li><li><code>@Null</code> 被注释的元素必须为 null</li><li><code>@NotNull</code> 被注释的元素必须不为 null</li><li><code>@AssertTrue</code> 被注释的元素必须为 true</li><li><code>@AssertFalse</code> 被注释的元素必须为 false</li><li><code>@Pattern(regex=,flag=)</code>被注释的元素必须符合指定的正则表达式</li><li><code>@Email</code> 被注释的元素必须是 Email 格式。</li><li><code>@Min(value)</code>被注释的元素必须是一个数字，其值必须大于等于指定的最小值</li><li><code>@Max(value)</code>被注释的元素必须是一个数字，其值必须小于等于指定的最大值</li><li><code>@DecimalMin(value)</code>被注释的元素必须是一个数字，其值必须大于等于指定的最小值</li><li><code>@DecimalMax(value)</code> 被注释的元素必须是一个数字，其值必须小于等于指定的最大值</li><li><code>@Size(max=, min=)</code>被注释的元素的大小必须在指定的范围内</li><li><code>@Digits(integer, fraction)</code>被注释的元素必须是一个数字，其值必须在可接受的范围内</li><li><code>@Past</code>被注释的元素必须是一个过去的日期</li><li><code>@Future</code> 被注释的元素必须是一个将来的日期</li><li>......</li></ul><h4 id="_6-2-验证请求体-requestbody" tabindex="-1"><a class="header-anchor" href="#_6-2-验证请求体-requestbody" aria-hidden="true">#</a> 6.2. 验证请求体(RequestBody)</h4><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Data</span>
<span class="token annotation punctuation">@AllArgsConstructor</span>
<span class="token annotation punctuation">@NoArgsConstructor</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@NotNull</span><span class="token punctuation">(</span>message <span class="token operator">=</span> <span class="token string">&quot;classId 不能为空&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> classId<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Size</span><span class="token punctuation">(</span>max <span class="token operator">=</span> <span class="token number">33</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@NotNull</span><span class="token punctuation">(</span>message <span class="token operator">=</span> <span class="token string">&quot;name 不能为空&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Pattern</span><span class="token punctuation">(</span>regexp <span class="token operator">=</span> <span class="token string">&quot;((^Man$|^Woman$|^UGM$))&quot;</span><span class="token punctuation">,</span> message <span class="token operator">=</span> <span class="token string">&quot;sex 值不在可选范围&quot;</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@NotNull</span><span class="token punctuation">(</span>message <span class="token operator">=</span> <span class="token string">&quot;sex 不能为空&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> sex<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@Email</span><span class="token punctuation">(</span>message <span class="token operator">=</span> <span class="token string">&quot;email 格式不正确&quot;</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@NotNull</span><span class="token punctuation">(</span>message <span class="token operator">=</span> <span class="token string">&quot;email 不能为空&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> email<span class="token punctuation">;</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>我们在需要验证的参数上加上了<code>@Valid</code>注解，如果验证失败，它将抛出<code>MethodArgumentNotValidException</code>。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@RestController</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/api&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PersonController</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/person&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Person</span><span class="token punctuation">&gt;</span></span> <span class="token function">getPerson</span><span class="token punctuation">(</span><span class="token annotation punctuation">@RequestBody</span> <span class="token annotation punctuation">@Valid</span> <span class="token class-name">Person</span> person<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token class-name">ResponseEntity</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">body</span><span class="token punctuation">(</span>person<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><h4 id="_6-3-验证请求参数-path-variables-和-request-parameters" tabindex="-1"><a class="header-anchor" href="#_6-3-验证请求参数-path-variables-和-request-parameters" aria-hidden="true">#</a> 6.3. 验证请求参数(Path Variables 和 Request Parameters)</h4><p><strong>一定一定不要忘记在类上加上 <code>@Validated</code> 注解了，这个参数可以告诉 Spring 去校验方法参数。</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@RestController</span>
<span class="token annotation punctuation">@RequestMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/api&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Validated</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">PersonController</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@GetMapping</span><span class="token punctuation">(</span><span class="token string">&quot;/person/{id}&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">Integer</span><span class="token punctuation">&gt;</span></span> <span class="token function">getPersonByID</span><span class="token punctuation">(</span><span class="token annotation punctuation">@Valid</span> <span class="token annotation punctuation">@PathVariable</span><span class="token punctuation">(</span><span class="token string">&quot;id&quot;</span><span class="token punctuation">)</span> <span class="token annotation punctuation">@Max</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">,</span>message <span class="token operator">=</span> <span class="token string">&quot;超过 id 的范围了&quot;</span><span class="token punctuation">)</span> <span class="token class-name">Integer</span> id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token class-name">ResponseEntity</span><span class="token punctuation">.</span><span class="token function">ok</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">body</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>更多关于如何在 Spring 项目中进行参数校验的内容，请看《<a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485783&amp;idx=1&amp;sn=a407f3b75efa17c643407daa7fb2acd6&amp;chksm=cea2469cf9d5cf8afbcd0a8a1c9cc4294d6805b8e01bee6f76bb2884c5bc15478e91459def49&amp;token=292197051&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">如何在 Spring/Spring Boot 中做参数校验？你需要了解的都在这里！<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>》这篇文章。</p><h3 id="_7-全局处理-controller-层异常" tabindex="-1"><a class="header-anchor" href="#_7-全局处理-controller-层异常" aria-hidden="true">#</a> 7. 全局处理 Controller 层异常</h3><p>介绍一下我们 Spring 项目必备的全局处理 Controller 层异常。</p><p><strong>相关注解：</strong></p><ol><li><code>@ControllerAdvice</code> :注解定义全局异常处理类</li><li><code>@ExceptionHandler</code> :注解声明异常处理方法</li></ol><p>如何使用呢？拿我们在第 5 节参数校验这块来举例子。如果方法参数不对的话就会抛出<code>MethodArgumentNotValidException</code>，我们来处理这个异常。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@ControllerAdvice</span>
<span class="token annotation punctuation">@ResponseBody</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">GlobalExceptionHandler</span> <span class="token punctuation">{</span>

    <span class="token doc-comment comment">/**
     * 请求参数异常处理
     */</span>
    <span class="token annotation punctuation">@ExceptionHandler</span><span class="token punctuation">(</span><span class="token class-name">MethodArgumentNotValidException</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token keyword">public</span> <span class="token class-name">ResponseEntity</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token operator">?</span><span class="token punctuation">&gt;</span></span> <span class="token function">handleMethodArgumentNotValidException</span><span class="token punctuation">(</span><span class="token class-name">MethodArgumentNotValidException</span> ex<span class="token punctuation">,</span> <span class="token class-name">HttpServletRequest</span> request<span class="token punctuation">)</span> <span class="token punctuation">{</span>
       <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>更多关于 Spring Boot 异常处理的内容，请看我的这两篇文章：</p><ol><li><a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485568&amp;idx=2&amp;sn=c5ba880fd0c5d82e39531fa42cb036ac&amp;chksm=cea2474bf9d5ce5dcbc6a5f6580198fdce4bc92ef577579183a729cb5d1430e4994720d59b34&amp;token=2133161636&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">SpringBoot 处理异常的几种常见姿势<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li><li><a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247486379&amp;idx=2&amp;sn=48c29ae65b3ed874749f0803f0e4d90e&amp;chksm=cea24460f9d5cd769ed53ad7e17c97a7963a89f5350e370be633db0ae8d783c3a3dbd58c70f8&amp;token=1054498516&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">使用枚举简单封装一个优雅的 Spring Boot 全局异常处理！<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a></li></ol><h3 id="_8-jpa-相关" tabindex="-1"><a class="header-anchor" href="#_8-jpa-相关" aria-hidden="true">#</a> 8. JPA 相关</h3><h4 id="_8-1-创建表" tabindex="-1"><a class="header-anchor" href="#_8-1-创建表" aria-hidden="true">#</a> 8.1. 创建表</h4><p><code>@Entity</code>声明一个类对应一个数据库实体。</p><p><code>@Table</code> 设置表名</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Entity</span>
<span class="token annotation punctuation">@Table</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;role&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Role</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Id</span>
    <span class="token annotation punctuation">@GeneratedValue</span><span class="token punctuation">(</span>strategy <span class="token operator">=</span> <span class="token class-name">GenerationType</span><span class="token punctuation">.</span>IDENTITY<span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> description<span class="token punctuation">;</span>
    省略getter<span class="token operator">/</span>setter<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h4 id="_8-2-创建主键" tabindex="-1"><a class="header-anchor" href="#_8-2-创建主键" aria-hidden="true">#</a> 8.2. 创建主键</h4><p><code>@Id</code> ：声明一个字段为主键。</p><p>使用<code>@Id</code>声明之后，我们还需要定义主键的生成策略。我们可以使用 <code>@GeneratedValue</code> 指定主键生成策略。</p><p><strong>1.通过 <code>@GeneratedValue</code>直接使用 JPA 内置提供的四种主键生成策略来指定主键生成策略。</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Id</span>
<span class="token annotation punctuation">@GeneratedValue</span><span class="token punctuation">(</span>strategy <span class="token operator">=</span> <span class="token class-name">GenerationType</span><span class="token punctuation">.</span>IDENTITY<span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>JPA 使用枚举定义了 4 种常见的主键生成策略，如下：</p><p><em>Guide 哥：枚举替代常量的一种用法</em></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">enum</span> <span class="token class-name">GenerationType</span> <span class="token punctuation">{</span>

    <span class="token doc-comment comment">/**
     * 使用一个特定的数据库表格来保存主键
     * 持久化引擎通过关系数据库的一张特定的表格来生成主键,
     */</span>
    TABLE<span class="token punctuation">,</span>

    <span class="token doc-comment comment">/**
     *在某些数据库中,不支持主键自增长,比如Oracle、PostgreSQL其提供了一种叫做&quot;序列(sequence)&quot;的机制生成主键
     */</span>
    SEQUENCE<span class="token punctuation">,</span>

    <span class="token doc-comment comment">/**
     * 主键自增长
     */</span>
    IDENTITY<span class="token punctuation">,</span>

    <span class="token doc-comment comment">/**
     *把主键生成策略交给持久化引擎(persistence engine),
     *持久化引擎会根据数据库在以上三种主键生成 策略中选择其中一种
     */</span>
    AUTO
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br></div></div><p><code>@GeneratedValue</code>注解默认使用的策略是<code>GenerationType.AUTO</code></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token annotation punctuation">@interface</span> <span class="token class-name">GeneratedValue</span> <span class="token punctuation">{</span>

    <span class="token class-name">GenerationType</span> <span class="token function">strategy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">default</span> AUTO<span class="token punctuation">;</span>
    <span class="token class-name">String</span> <span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">default</span> <span class="token string">&quot;&quot;</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>一般使用 MySQL 数据库的话，使用<code>GenerationType.IDENTITY</code>策略比较普遍一点（分布式系统的话需要另外考虑使用分布式 ID）。</p><p><strong>2.通过 <code>@GenericGenerator</code>声明一个主键策略，然后 <code>@GeneratedValue</code>使用这个策略</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Id</span>
<span class="token annotation punctuation">@GeneratedValue</span><span class="token punctuation">(</span>generator <span class="token operator">=</span> <span class="token string">&quot;IdentityIdGenerator&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@GenericGenerator</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;IdentityIdGenerator&quot;</span><span class="token punctuation">,</span> strategy <span class="token operator">=</span> <span class="token string">&quot;identity&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>等价于：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Id</span>
<span class="token annotation punctuation">@GeneratedValue</span><span class="token punctuation">(</span>strategy <span class="token operator">=</span> <span class="token class-name">GenerationType</span><span class="token punctuation">.</span>IDENTITY<span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>jpa 提供的主键生成策略有如下几种：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DefaultIdentifierGeneratorFactory</span>
		<span class="token keyword">implements</span> <span class="token class-name">MutableIdentifierGeneratorFactory</span><span class="token punctuation">,</span> <span class="token class-name">Serializable</span><span class="token punctuation">,</span> <span class="token class-name">ServiceRegistryAwareService</span> <span class="token punctuation">{</span>

	<span class="token annotation punctuation">@SuppressWarnings</span><span class="token punctuation">(</span><span class="token string">&quot;deprecation&quot;</span><span class="token punctuation">)</span>
	<span class="token keyword">public</span> <span class="token class-name">DefaultIdentifierGeneratorFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;uuid2&quot;</span><span class="token punctuation">,</span> <span class="token class-name">UUIDGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;guid&quot;</span><span class="token punctuation">,</span> <span class="token class-name">GUIDGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>			<span class="token comment">// can be done with UUIDGenerator + strategy</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;uuid&quot;</span><span class="token punctuation">,</span> <span class="token class-name">UUIDHexGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>			<span class="token comment">// &quot;deprecated&quot; for new use</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;uuid.hex&quot;</span><span class="token punctuation">,</span> <span class="token class-name">UUIDHexGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span> 	<span class="token comment">// uuid.hex is deprecated</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;assigned&quot;</span><span class="token punctuation">,</span> <span class="token class-name">Assigned</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;identity&quot;</span><span class="token punctuation">,</span> <span class="token class-name">IdentityGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;select&quot;</span><span class="token punctuation">,</span> <span class="token class-name">SelectGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;sequence&quot;</span><span class="token punctuation">,</span> <span class="token class-name">SequenceStyleGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;seqhilo&quot;</span><span class="token punctuation">,</span> <span class="token class-name">SequenceHiLoGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;increment&quot;</span><span class="token punctuation">,</span> <span class="token class-name">IncrementGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;foreign&quot;</span><span class="token punctuation">,</span> <span class="token class-name">ForeignGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;sequence-identity&quot;</span><span class="token punctuation">,</span> <span class="token class-name">SequenceIdentityGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;enhanced-sequence&quot;</span><span class="token punctuation">,</span> <span class="token class-name">SequenceStyleGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token function">register</span><span class="token punctuation">(</span> <span class="token string">&quot;enhanced-table&quot;</span><span class="token punctuation">,</span> <span class="token class-name">TableGenerator</span><span class="token punctuation">.</span><span class="token keyword">class</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>

	<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">register</span><span class="token punctuation">(</span><span class="token class-name">String</span> strategy<span class="token punctuation">,</span> <span class="token class-name">Class</span> generatorClass<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		LOG<span class="token punctuation">.</span><span class="token function">debugf</span><span class="token punctuation">(</span> <span class="token string">&quot;Registering IdentifierGenerator strategy [%s] -&gt; [%s]&quot;</span><span class="token punctuation">,</span> strategy<span class="token punctuation">,</span> generatorClass<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">final</span> <span class="token class-name">Class</span> previous <span class="token operator">=</span> generatorStrategyToClassNameMap<span class="token punctuation">.</span><span class="token function">put</span><span class="token punctuation">(</span> strategy<span class="token punctuation">,</span> generatorClass <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span> previous <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span>
			LOG<span class="token punctuation">.</span><span class="token function">debugf</span><span class="token punctuation">(</span> <span class="token string">&quot;    - overriding [%s]&quot;</span><span class="token punctuation">,</span> previous<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br></div></div><h4 id="_8-3-设置字段类型" tabindex="-1"><a class="header-anchor" href="#_8-3-设置字段类型" aria-hidden="true">#</a> 8.3. 设置字段类型</h4><p><code>@Column</code> 声明字段。</p><p><strong>示例：</strong></p><p>设置属性 userName 对应的数据库字段名为 user_name，长度为 32，非空</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;user_name&quot;</span><span class="token punctuation">,</span> nullable <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">,</span> length<span class="token operator">=</span><span class="token number">32</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> userName<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>设置字段类型并且加默认值，这个还是挺常用的。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>columnDefinition <span class="token operator">=</span> <span class="token string">&quot;tinyint(1) default 1&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Boolean</span> enabled<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h4 id="_8-4-指定不持久化特定字段" tabindex="-1"><a class="header-anchor" href="#_8-4-指定不持久化特定字段" aria-hidden="true">#</a> 8.4. 指定不持久化特定字段</h4><p><code>@Transient</code> ：声明不需要与数据库映射的字段，在保存的时候不需要保存进数据库 。</p><p>如果我们想让<code>secrect</code> 这个字段不被持久化，可以使用 <code>@Transient</code>关键字声明。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Entity</span><span class="token punctuation">(</span>name<span class="token operator">=</span><span class="token string">&quot;USER&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>

    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token annotation punctuation">@Transient</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> secrect<span class="token punctuation">;</span> <span class="token comment">// not persistent because of @Transient</span>

<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><p>除了 <code>@Transient</code>关键字声明， 还可以采用下面几种方法：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">static</span> <span class="token class-name">String</span> secrect<span class="token punctuation">;</span> <span class="token comment">// not persistent because of static</span>
<span class="token keyword">final</span> <span class="token class-name">String</span> secrect <span class="token operator">=</span> <span class="token string">&quot;Satish&quot;</span><span class="token punctuation">;</span> <span class="token comment">// not persistent because of final</span>
<span class="token keyword">transient</span> <span class="token class-name">String</span> secrect<span class="token punctuation">;</span> <span class="token comment">// not persistent because of transient</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>一般使用注解的方式比较多。</p><h4 id="_8-5-声明大字段" tabindex="-1"><a class="header-anchor" href="#_8-5-声明大字段" aria-hidden="true">#</a> 8.5. 声明大字段</h4><p><code>@Lob</code>:声明某个字段为大字段。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Lob</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> content<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>更详细的声明：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Lob</span>
<span class="token comment">//指定 Lob 类型数据的获取策略， FetchType.EAGER 表示非延迟加载，而 FetchType.LAZY 表示延迟加载 ；</span>
<span class="token annotation punctuation">@Basic</span><span class="token punctuation">(</span>fetch <span class="token operator">=</span> <span class="token class-name">FetchType</span><span class="token punctuation">.</span>EAGER<span class="token punctuation">)</span>
<span class="token comment">//columnDefinition 属性指定数据表对应的 Lob 字段类型</span>
<span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;content&quot;</span><span class="token punctuation">,</span> columnDefinition <span class="token operator">=</span> <span class="token string">&quot;LONGTEXT NOT NULL&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">String</span> content<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h4 id="_8-6-创建枚举类型的字段" tabindex="-1"><a class="header-anchor" href="#_8-6-创建枚举类型的字段" aria-hidden="true">#</a> 8.6. 创建枚举类型的字段</h4><p>可以使用枚举类型的字段，不过枚举字段要用<code>@Enumerated</code>注解修饰。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">enum</span> <span class="token class-name">Gender</span> <span class="token punctuation">{</span>
    <span class="token function">MALE</span><span class="token punctuation">(</span><span class="token string">&quot;男性&quot;</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function">FEMALE</span><span class="token punctuation">(</span><span class="token string">&quot;女性&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">private</span> <span class="token class-name">String</span> value<span class="token punctuation">;</span>
    <span class="token class-name">Gender</span><span class="token punctuation">(</span><span class="token class-name">String</span> str<span class="token punctuation">)</span><span class="token punctuation">{</span>
        value<span class="token operator">=</span>str<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Entity</span>
<span class="token annotation punctuation">@Table</span><span class="token punctuation">(</span>name <span class="token operator">=</span> <span class="token string">&quot;role&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Role</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Id</span>
    <span class="token annotation punctuation">@GeneratedValue</span><span class="token punctuation">(</span>strategy <span class="token operator">=</span> <span class="token class-name">GenerationType</span><span class="token punctuation">.</span>IDENTITY<span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">Long</span> id<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> description<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@Enumerated</span><span class="token punctuation">(</span><span class="token class-name">EnumType</span><span class="token punctuation">.</span>STRING<span class="token punctuation">)</span>
    <span class="token keyword">private</span> <span class="token class-name">Gender</span> gender<span class="token punctuation">;</span>
    省略getter<span class="token operator">/</span>setter<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>数据库里面对应存储的是 MALE/FEMALE。</p><h4 id="_8-7-增加审计功能" tabindex="-1"><a class="header-anchor" href="#_8-7-增加审计功能" aria-hidden="true">#</a> 8.7. 增加审计功能</h4><p>只要继承了 <code>AbstractAuditBase</code>的类都会默认加上下面四个字段。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Data</span>
<span class="token annotation punctuation">@AllArgsConstructor</span>
<span class="token annotation punctuation">@NoArgsConstructor</span>
<span class="token annotation punctuation">@MappedSuperclass</span>
<span class="token annotation punctuation">@EntityListeners</span><span class="token punctuation">(</span>value <span class="token operator">=</span> <span class="token class-name">AuditingEntityListener</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">AbstractAuditBase</span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@CreatedDate</span>
    <span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>updatable <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@JsonIgnore</span>
    <span class="token keyword">private</span> <span class="token class-name">Instant</span> createdAt<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@LastModifiedDate</span>
    <span class="token annotation punctuation">@JsonIgnore</span>
    <span class="token keyword">private</span> <span class="token class-name">Instant</span> updatedAt<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@CreatedBy</span>
    <span class="token annotation punctuation">@Column</span><span class="token punctuation">(</span>updatable <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">)</span>
    <span class="token annotation punctuation">@JsonIgnore</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> createdBy<span class="token punctuation">;</span>

    <span class="token annotation punctuation">@LastModifiedBy</span>
    <span class="token annotation punctuation">@JsonIgnore</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> updatedBy<span class="token punctuation">;</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br></div></div><p>我们对应的审计功能对应地配置类可能是下面这样的（Spring Security 项目）:</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code>
<span class="token annotation punctuation">@Configuration</span>
<span class="token annotation punctuation">@EnableJpaAuditing</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">AuditSecurityConfiguration</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@Bean</span>
    <span class="token class-name">AuditorAware</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">String</span><span class="token punctuation">&gt;</span></span> <span class="token function">auditorAware</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-&gt;</span> <span class="token class-name">Optional</span><span class="token punctuation">.</span><span class="token function">ofNullable</span><span class="token punctuation">(</span><span class="token class-name">SecurityContextHolder</span><span class="token punctuation">.</span><span class="token function">getContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token class-name">SecurityContext</span><span class="token operator">::</span><span class="token function">getAuthentication</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token class-name">Authentication</span><span class="token operator">::</span><span class="token function">isAuthenticated</span><span class="token punctuation">)</span>
                <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token class-name">Authentication</span><span class="token operator">::</span><span class="token function">getName</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>简单介绍一下上面涉及到的一些注解：</p><ol><li><p><code>@CreatedDate</code>: 表示该字段为创建时间字段，在这个实体被 insert 的时候，会设置值</p></li><li><p><code>@CreatedBy</code> :表示该字段为创建人，在这个实体被 insert 的时候，会设置值</p><p><code>@LastModifiedDate</code>、<code>@LastModifiedBy</code>同理。</p></li></ol><p><code>@EnableJpaAuditing</code>：开启 JPA 审计功能。</p><h4 id="_8-8-删除-修改数据" tabindex="-1"><a class="header-anchor" href="#_8-8-删除-修改数据" aria-hidden="true">#</a> 8.8. 删除/修改数据</h4><p><code>@Modifying</code> 注解提示 JPA 该操作是修改操作,注意还要配合<code>@Transactional</code>注解使用。</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Repository</span>
<span class="token keyword">public</span> <span class="token keyword">interface</span> <span class="token class-name">UserRepository</span> <span class="token keyword">extends</span> <span class="token class-name">JpaRepository</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">User</span><span class="token punctuation">,</span> <span class="token class-name">Integer</span><span class="token punctuation">&gt;</span></span> <span class="token punctuation">{</span>

    <span class="token annotation punctuation">@Modifying</span>
    <span class="token annotation punctuation">@Transactional</span><span class="token punctuation">(</span>rollbackFor <span class="token operator">=</span> <span class="token class-name">Exception</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
    <span class="token keyword">void</span> <span class="token function">deleteByUserName</span><span class="token punctuation">(</span><span class="token class-name">String</span> userName<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h4 id="_8-9-关联关系" tabindex="-1"><a class="header-anchor" href="#_8-9-关联关系" aria-hidden="true">#</a> 8.9. 关联关系</h4><ul><li><code>@OneToOne</code> 声明一对一关系</li><li><code>@OneToMany</code> 声明一对多关系</li><li><code>@ManyToOne</code> 声明多对一关系</li><li><code>@MangToMang</code> 声明多对多关系</li></ul><p>更多关于 Spring Boot JPA 的文章请看我的这篇文章：<a href="https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&amp;mid=2247485689&amp;idx=1&amp;sn=061b32c2222869932be5631fb0bb5260&amp;chksm=cea24732f9d5ce24a356fb3675170e7843addbfcc79ee267cfdb45c83fc7e90babf0f20d22e1&amp;token=292197051&amp;lang=zh_CN#rd" target="_blank" rel="noopener noreferrer">一文搞懂如何在 Spring Boot 正确中使用 JPA<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a> 。</p><h3 id="_9-事务-transactional" tabindex="-1"><a class="header-anchor" href="#_9-事务-transactional" aria-hidden="true">#</a> 9. 事务 <code>@Transactional</code></h3><p>在要开启事务的方法上使用<code>@Transactional</code>注解即可!</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Transactional</span><span class="token punctuation">(</span>rollbackFor <span class="token operator">=</span> <span class="token class-name">Exception</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>我们知道 Exception 分为运行时异常 RuntimeException 和非运行时异常。在<code>@Transactional</code>注解中如果不配置<code>rollbackFor</code>属性,那么事务只会在遇到<code>RuntimeException</code>的时候才会回滚,加上<code>rollbackFor=Exception.class</code>,可以让事务在遇到非运行时异常时也回滚。</p><p><code>@Transactional</code> 注解一般可以作用在<code>类</code>或者<code>方法</code>上。</p><ul><li><strong>作用于类</strong>：当把<code>@Transactional</code> 注解放在类上时，表示所有该类的 public 方法都配置相同的事务属性信息。</li><li><strong>作用于方法</strong>：当类配置了<code>@Transactional</code>，方法也配置了<code>@Transactional</code>，方法的事务会覆盖类的事务配置信息。</li></ul><p>更多关于 Spring 事务的内容请查看我的这篇文章：<a href="/system-design/framework/spring/spring-transaction.html" class="">可能是最漂亮的 Spring 事务管理详解</a> 。</p><h3 id="_10-json-数据处理" tabindex="-1"><a class="header-anchor" href="#_10-json-数据处理" aria-hidden="true">#</a> 10. json 数据处理</h3><h4 id="_10-1-过滤-json-数据" tabindex="-1"><a class="header-anchor" href="#_10-1-过滤-json-数据" aria-hidden="true">#</a> 10.1. 过滤 json 数据</h4><p><strong><code>@JsonIgnoreProperties</code> 作用在类上用于过滤掉特定字段不返回或者不解析。</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token comment">//生成json时将userRoles属性过滤</span>
<span class="token annotation punctuation">@JsonIgnoreProperties</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token string">&quot;userRoles&quot;</span><span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">String</span> userName<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> fullName<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> password<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">UserRole</span><span class="token punctuation">&gt;</span></span> userRoles <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><p><strong><code>@JsonIgnore</code>一般用于类的属性上，作用和上面的<code>@JsonIgnoreProperties</code> 一样。</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">User</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token class-name">String</span> userName<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> fullName<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> password<span class="token punctuation">;</span>
   <span class="token comment">//生成json时将userRoles属性过滤</span>
    <span class="token annotation punctuation">@JsonIgnore</span>
    <span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token class-name">UserRole</span><span class="token punctuation">&gt;</span></span> userRoles <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token generics"><span class="token punctuation">&lt;</span><span class="token punctuation">&gt;</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h4 id="_10-2-格式化-json-数据" tabindex="-1"><a class="header-anchor" href="#_10-2-格式化-json-数据" aria-hidden="true">#</a> 10.2. 格式化 json 数据</h4><p><code>@JsonFormat</code>一般用来格式化 json 数据。</p><p>比如：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@JsonFormat</span><span class="token punctuation">(</span>shape<span class="token operator">=</span><span class="token class-name">JsonFormat<span class="token punctuation">.</span>Shape</span><span class="token punctuation">.</span>STRING<span class="token punctuation">,</span> pattern<span class="token operator">=</span><span class="token string">&quot;yyyy-MM-dd&#39;T&#39;HH:mm:ss.SSS&#39;Z&#39;&quot;</span><span class="token punctuation">,</span> timezone<span class="token operator">=</span><span class="token string">&quot;GMT&quot;</span><span class="token punctuation">)</span>
<span class="token keyword">private</span> <span class="token class-name">Date</span> date<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h4 id="_10-3-扁平化对象" tabindex="-1"><a class="header-anchor" href="#_10-3-扁平化对象" aria-hidden="true">#</a> 10.3. 扁平化对象</h4><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Getter</span>
<span class="token annotation punctuation">@Setter</span>
<span class="token annotation punctuation">@ToString</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Account</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token class-name">Location</span> location<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">PersonInfo</span> personInfo<span class="token punctuation">;</span>

  <span class="token annotation punctuation">@Getter</span>
  <span class="token annotation punctuation">@Setter</span>
  <span class="token annotation punctuation">@ToString</span>
  <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">Location</span> <span class="token punctuation">{</span>
     <span class="token keyword">private</span> <span class="token class-name">String</span> provinceName<span class="token punctuation">;</span>
     <span class="token keyword">private</span> <span class="token class-name">String</span> countyName<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token annotation punctuation">@Getter</span>
  <span class="token annotation punctuation">@Setter</span>
  <span class="token annotation punctuation">@ToString</span>
  <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">PersonInfo</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> userName<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">String</span> fullName<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><p>未扁平化之前：</p><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code><span class="token punctuation">{</span>
    <span class="token property">&quot;location&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">&quot;provinceName&quot;</span><span class="token operator">:</span><span class="token string">&quot;湖北&quot;</span><span class="token punctuation">,</span>
        <span class="token property">&quot;countyName&quot;</span><span class="token operator">:</span><span class="token string">&quot;武汉&quot;</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">&quot;personInfo&quot;</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token property">&quot;userName&quot;</span><span class="token operator">:</span> <span class="token string">&quot;coder1234&quot;</span><span class="token punctuation">,</span>
        <span class="token property">&quot;fullName&quot;</span><span class="token operator">:</span> <span class="token string">&quot;shaungkou&quot;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>使用<code>@JsonUnwrapped</code> 扁平对象之后：</p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@Getter</span>
<span class="token annotation punctuation">@Setter</span>
<span class="token annotation punctuation">@ToString</span>
<span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">Account</span> <span class="token punctuation">{</span>
    <span class="token annotation punctuation">@JsonUnwrapped</span>
    <span class="token keyword">private</span> <span class="token class-name">Location</span> location<span class="token punctuation">;</span>
    <span class="token annotation punctuation">@JsonUnwrapped</span>
    <span class="token keyword">private</span> <span class="token class-name">PersonInfo</span> personInfo<span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><div class="language-json ext-json line-numbers-mode"><pre class="language-json"><code><span class="token punctuation">{</span>
  <span class="token property">&quot;provinceName&quot;</span><span class="token operator">:</span><span class="token string">&quot;湖北&quot;</span><span class="token punctuation">,</span>
  <span class="token property">&quot;countyName&quot;</span><span class="token operator">:</span><span class="token string">&quot;武汉&quot;</span><span class="token punctuation">,</span>
  <span class="token property">&quot;userName&quot;</span><span class="token operator">:</span> <span class="token string">&quot;coder1234&quot;</span><span class="token punctuation">,</span>
  <span class="token property">&quot;fullName&quot;</span><span class="token operator">:</span> <span class="token string">&quot;shaungkou&quot;</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="_11-测试相关" tabindex="-1"><a class="header-anchor" href="#_11-测试相关" aria-hidden="true">#</a> 11. 测试相关</h3><p><strong><code>@ActiveProfiles</code>一般作用于测试类上， 用于声明生效的 Spring 配置文件。</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code><span class="token annotation punctuation">@SpringBootTest</span><span class="token punctuation">(</span>webEnvironment <span class="token operator">=</span> RANDOM_PORT<span class="token punctuation">)</span>
<span class="token annotation punctuation">@ActiveProfiles</span><span class="token punctuation">(</span><span class="token string">&quot;test&quot;</span><span class="token punctuation">)</span>
<span class="token annotation punctuation">@Slf4j</span>
<span class="token keyword">public</span> <span class="token keyword">abstract</span> <span class="token keyword">class</span> <span class="token class-name">TestBase</span> <span class="token punctuation">{</span>
  <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><strong><code>@Test</code>声明一个方法为测试方法</strong></p><p><strong><code>@Transactional</code>被声明的测试方法的数据会回滚，避免污染测试数据。</strong></p><p><strong><code>@WithMockUser</code> Spring Security 提供的，用来模拟一个真实用户，并且可以赋予权限。</strong></p><div class="language-java ext-java line-numbers-mode"><pre class="language-java"><code>    <span class="token annotation punctuation">@Test</span>
    <span class="token annotation punctuation">@Transactional</span>
    <span class="token annotation punctuation">@WithMockUser</span><span class="token punctuation">(</span>username <span class="token operator">=</span> <span class="token string">&quot;user-id-18163138155&quot;</span><span class="token punctuation">,</span> authorities <span class="token operator">=</span> <span class="token string">&quot;ROLE_TEACHER&quot;</span><span class="token punctuation">)</span>
    <span class="token keyword">void</span> <span class="token function">should_import_student_success</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Exception</span> <span class="token punctuation">{</span>
        <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
    <span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><em>暂时总结到这里吧！虽然花了挺长时间才写完，不过可能还是会一些常用的注解的被漏掉，所以，我将文章也同步到了 Github 上去，Github 地址： 欢迎完善！</em></p><p>本文已经收录进我的 75K Star 的 Java 开源项目 JavaGuide：<a href="https://github.com/Snailclimb/JavaGuide" target="_blank" rel="noopener noreferrer">https://github.com/Snailclimb/JavaGuide<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span></a>。</p><!--]--></div><!----><footer class="page-meta"><div class="meta-item edit-link"><a href="https://github.com/Snailclimb/JavaGuide/edit/main/docs/system-design/framework/spring/spring-common-annotations.md" rel="noopener noreferrer" target="_blank" arialabel="编辑此页" class="nav-link label"><!--[--><svg xmlns="http://www.w3.org/2000/svg" class="icon edit-icon" viewbox="0 0 1024 1024" arialabelledby="edit"><title id="edit" lang="en">edit icon</title><g fill="currentColor"><path d="M430.818 653.65a60.46 60.46 0 0 1-50.96-93.281l71.69-114.012 7.773-10.365L816.038 80.138A60.46 60.46 0 0 1 859.225 62a60.46 60.46 0 0 1 43.186 18.138l43.186 43.186a60.46 60.46 0 0 1 0 86.373L588.879 565.55l-8.637 8.637-117.466 68.234a60.46 60.46 0 0 1-31.958 11.229z"></path><path d="M728.802 962H252.891A190.883 190.883 0 0 1 62.008 771.98V296.934a190.883 190.883 0 0 1 190.883-192.61h267.754a60.46 60.46 0 0 1 0 120.92H252.891a69.962 69.962 0 0 0-69.098 69.099V771.98a69.962 69.962 0 0 0 69.098 69.098h475.911A69.962 69.962 0 0 0 797.9 771.98V503.363a60.46 60.46 0 1 1 120.922 0V771.98A190.883 190.883 0 0 1 728.802 962z"></path></g></svg><!--]-->编辑此页<span><svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewbox="0 0 100 100" width="15" height="15"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path><polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!----></a></div><div class="meta-item update-time"><span class="label">上次编辑于: </span><span class="info">2022/3/12 13:54:41</span></div><div class="meta-item contributors"><span class="label">贡献者: </span><!--[--><!--[--><span class="contributor" title="email: koushuangbwcx@163.com">guide</span>,<!--]--><!--[--><span class="contributor" title="email: dev.sunflower@gmail.com">东三环牛哥</span><!--]--><!--]--></div></footer><nav class="page-nav"><a href="/system-design/framework/spring/spring-knowledge-and-questions-summary.html" class="nav-link prev" arialabel="Spring常见问题总结"><div class="hint"><span class="arrow left"></span>上一页</div><div class="link"><!---->Spring常见问题总结</div></a><a href="/system-design/framework/spring/spring-transaction.html" class="nav-link next" arialabel="Spring 事务总结"><div class="hint">下一页<span class="arrow right"></span></div><div class="link">Spring 事务总结<!----></div></a></nav><!----><!----></main><!--]--><footer class="footer-wrapper"><div class="footer"><a href="https://beian.miit.gov.cn/" target="_blank">鄂ICP备2020015769号-1</a></div><div class="copyright">Copyright © 2022 Guide</div></footer></div><!--]--><!----><!--]--></div>
    <script type="module" src="/assets/app.93341f6d.js" defer></script>
  </body>
</html>
